﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Web;

namespace BusinessLogicLayer
{
    public class PersianDateTime
    {
        PersianCalendar PersianCalendar = new PersianCalendar();

        public PersianDateTime(DateTime Gregorian)
        {
            Year = PersianCalendar.GetYear(Gregorian);
            Month = PersianCalendar.GetMonth(Gregorian);
            Day = PersianCalendar.GetDayOfMonth(Gregorian);
            Hour = Gregorian.Hour;
            Minute = Gregorian.Minute;
            Second = Gregorian.Second;
            Millisecond = Gregorian.Millisecond;
        }

        public PersianDateTime(int Year, int Month, int Day, int Hour, int Minute, int Second, int Millisecond)
        {
            this.Year = Year;
            this.Month = Month;
            this.Day = Day;
            this.Hour = Hour;
            this.Minute = Minute;
            this.Second = Second;
            this.Millisecond = Millisecond;
        }

        public PersianDateTime(int Year, int Month, int Day)
        {
            this.Year = Year;
            this.Month = Month;
            this.Day = Day;
        }

        public int Year { get; set; }
        public int Month { get; set; }
        public int Day { get; set; }
        public int Hour { get; set; }
        public int Minute { get; set; }
        public int Second { get; set; }
        public int Millisecond { get; set; }

        public int Identifier { get { return (Year * 10000 + Month * 100 + Day); } }

        public void AddMonth(int m)
        {
            if (m > 0)
            {
                Year += (m / 12) + ((Month + (m % 12)) > 12 ? 1 : 0);
                Month = ((Month - 1 + m) % 12) + 1;
            }
            else if (m < 0)
            {
                m = -m;
                Year -= (m / 12) + ((Month - (m % 12)) < 1 ? 1 : 0);
                Month = ((Month - 1 - m) % 12) + 13;
            }
        }

        public PersianDateTime AddMonthClone(int m)
        {
            int Year = this.Year;
            int Month = this.Month;
            if (m > 0)
            {
                Year += (m / 12) + ((Month + (m % 12)) > 12 ? 1 : 0);
                Month = ((Month - 1 + m) % 12) + 1;
            }
            else if (m < 0)
            {
                m = -m;
                Year -= (m / 12) + ((Month - (m % 12)) < 1 ? 1 : 0);
                Month = ((Month - 1 - m) % 12) + 13;
            }
            return (new PersianDateTime(Year, Month, Day, Hour, Minute, Second, Millisecond));
        }

        public PersianDateTime Clone()
        {
            return (new PersianDateTime(Year, Month, Day, Hour, Minute, Second, Millisecond));
        }

        public DateTime ToGregorian()
        {
            return (new DateTime(Year, Month, Day, Hour, Minute, Second, Millisecond, PersianCalendar));
        }
    }

    public static class PersianDateTimeExtension
    {
        public static string[] PersianDayOfWeekNames()
        {
            return (new string[] { "شنبه", "یکشنبه", "دوشنبه", "سه شنبه", "چهارشنبه", "پنج شنبه", "جمعه" });
        }

        public static string[] PersianMonthNames()
        {
            return (new string[] { "فروردین", "اردیبهشت", "خرداد", "تیر", "مرداد", "شهریور", "مهر", "آبان", "آذر", "دی", "بهمن", "اسفند" });
        }

        public static string ToShortHijriSolarDateString(this DateTime date)
        {
            PersianCalendar PersianCalendar = new PersianCalendar();
            return (date.ToShortDateString(PersianCalendar));
        }

        public static string ToShortHijriLunarDateString(this DateTime DateTime)
        {
            HijriCalendar HijriCalendar = new HijriCalendar();
            return (DateTime.ToShortDateString(HijriCalendar));
        }

        public static string ToHijriSolarString(this DateTime DateTime)
        {
            PersianCalendar PersianCalendar = new PersianCalendar();
            return (DateTime.ToString(PersianCalendar));
        }

        public static string ToHijriLunarString(this DateTime DateTime)
        {
            HijriCalendar HijriCalendar = new HijriCalendar();
            return (DateTime.ToString(HijriCalendar));
        }

        public static string ToShortDateString(this DateTime DateTime, Calendar TargetCalendar)
        {
            int day = TargetCalendar.GetDayOfMonth(DateTime);
            int month = TargetCalendar.GetMonth(DateTime);
            int year = TargetCalendar.GetYear(DateTime);
            return (year + "/" + month.ToString("00") + "/" + day.ToString("00"));
        }

        public static string ToString(this DateTime DateTime, Calendar TargetCalendar)
        {
            int day = TargetCalendar.GetDayOfMonth(DateTime);
            int month = TargetCalendar.GetMonth(DateTime);
            int year = TargetCalendar.GetYear(DateTime);
            return (year + "/" + month.ToString("00") + "/" + day.ToString("00") + " " + DateTime.Hour.ToString("00") + ":" + DateTime.Minute.ToString("00") + ":" + DateTime.Second.ToString("00"));
        }

        public static DateTime Parse(string DateTime, Calendar SourceCalendar)
        {
            int year = int.Parse(DateTime.Substring(0, 4));
            int month = int.Parse(DateTime.Substring(5, 2));
            int day = int.Parse(DateTime.Substring(8, 2));
            if (DateTime.Length > 10)
            {
                int hour = int.Parse(DateTime.Substring(11, 2));
                int minute = int.Parse(DateTime.Substring(14, 2));
                int second = int.Parse(DateTime.Substring(17, 2));
                return (new DateTime(year, month, day, hour, minute, second, SourceCalendar));
            }
            return (new DateTime(year, month, day, SourceCalendar));
        }

        public static bool TryParse(string DateTime, Calendar SourceCalendar, out DateTime Result)
        {
            try
            {
                Result = Parse(DateTime, SourceCalendar);
                return true;
            }
            catch (Exception)
            {
                Result = new DateTime();
                return false;
            }
        }

        public static DateTime ParseHijriSolar(string DateTime)
        {
            PersianCalendar PersianCalendar = new PersianCalendar();
            return (Parse(DateTime, PersianCalendar));
        }

        public static DateTime ParseHijriLunar(string DateTime)
        {
            HijriCalendar HijriCalendar = new HijriCalendar();
            return (Parse(DateTime, HijriCalendar));
        }

        public static bool TryParseHijriSolar(string DateTime, out DateTime Result)
        {
            PersianCalendar PersianCalendar = new PersianCalendar();
            return (TryParse(DateTime, PersianCalendar, out Result));
        }

        public static bool TryParseHijriLunar(string DateTime, bool IncludeTime, out DateTime Result)
        {
            HijriCalendar HijriCalendar = new HijriCalendar();
            return (TryParse(DateTime, HijriCalendar, out Result));
        }
    }
}